【题解】 [十二省联考2019]异或粽子 可持久化Trie树 luoguP5283 | Qiuly's blog!

【题解】 [十二省联考2019]异或粽子 可持久化Trie树 luoguP5283

要是我不是 $\texttt{HN}​$ 的该多好,今年十二省联考两道傻逼题,一道异或粽子,一道十二响……

[十二省联考2019]异或粽子,可持久化 $trie​$ 树的板子题,比最大异或和还要板子些。相信 $60​$ 分入门者都会做,那么 $100​$ 分的话我们上可持久化 $trie​$ 树维护前缀异或和,嗯没错就像主席树那样。然后对于每个节点的可持久化 $trie​$ 树我们将其当成区间右端点,然后在此位置上的 $trie​$ 树中贪心寻找左端点即可。

寻找前 $K$ 大区间的具体操作如下:

1
2
3
4
5
6
7
8
9
10
for(ll i=1;i<=n;++i) 
q.push(MKP(T.query(T.root[i],sum[i],qrank[i]=1),i));
/*对于每一个右端点,找一个第一大(最优)的左端点放入优先队列*/
ll ans=0;
while(k--) {
ll i=q.top().second;/*取出当前最优元素*/
ans+=q.top().first;q.pop();
if(qrank[i]!=i) q.push(MKP(T.query(T.root[i],sum[i],++qrank[i]),i));
/*更新队列元素*/
}

复杂度大约是 $O(nlogn)​$ 级别。

Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <queue>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define MKP make_pair

const ll N=5e5+2;
const ll logN=33;
const ll inf=1e9+9;

template <typename _Tp> inline void IN(_Tp&x) {
char ch;bool flag=0;x=0;
while(ch=getchar(),!isdigit(ch)) if(ch=='-') flag=1;
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
if(flag) x=-x;
}

ll n,k,sum[N],qrank[N];
priority_queue<pair<ll,ll> > q;

struct Trie {
ll ch[N*logN][2],sum[N*logN],root[N],tot;
ll newnode(ll x) {
++tot,ch[tot][0]=ch[x][0],ch[tot][1]=ch[x][1];
sum[tot]=sum[x];return tot;
}
void Insert(ll&rt,ll val) {
rt=newnode(rt),++sum[rt];
ll now=rt;
for(ll i=31;~i;--i) {
bool son=(val>>i)&1;
ch[now][son]=newnode(ch[now][son]);
now=ch[now][son],++sum[now];
}return;
}
ll query(ll now,ll val,ll k) {
ll ans=0;
for(ll i=31;~i;--i) {
bool son=!((val>>i)&1);
if(k<=sum[ch[now][son]]) now=ch[now][son],ans|=(1u<<i);
else k-=sum[ch[now][son]],now=ch[now][!son];
}return ans;
}
}T;

int main(){
IN(n),IN(k);
for(ll i=1,x;i<=n;++i) IN(x),sum[i]=sum[i-1]^x;
for(ll i=0;i<=n;++i) {
if(i) T.root[i]=T.root[i-1];
T.Insert(T.root[i],sum[i]);
}
for(ll i=1;i<=n;++i)
q.push(MKP(T.query(T.root[i],sum[i],qrank[i]=1),i));
ll ans=0;
while(k--) {
ll i=q.top().second;
ans+=q.top().first;q.pop();
if(qrank[i]!=i) q.push(MKP(T.query(T.root[i],sum[i],++qrank[i]),i));
}
printf("%lld\n",ans);
return 0;
}

本文标题:【题解】 [十二省联考2019]异或粽子 可持久化Trie树 luoguP5283

文章作者:Qiuly

发布时间:2019年04月19日 - 00:00

最后更新:2019年04月19日 - 19:34

原始链接:http://qiulyblog.github.io/2019/04/19/[题解]luoguP5283/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。